package com.yhx.security.gfoBank.file;


import java.io.*;

import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.yhx.myDemo.Student;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomStringUtils;

import cfca.sadk.cgb.toolkit.BASE64Toolkit;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

public class FileEncryptAndSign{
	/**
	 * 
	 * @param outPath 文件输出路劲
	 * @param newFileName 生成的文件名
	 * @param srcFullPath 源文件
	 * @param certPath 私钥
	 * @throws Exception
	 */
	public static byte[] excute(String outPath, String newFileName, String srcFullPath, String certPath, List<String> str) throws Exception {
		try{
			File tmpPath=new File(outPath);
			if(!tmpPath.exists()){
				tmpPath.mkdirs();
			}



		/*	Student o = new Student();
			o.setName("jfiejfie");
			o.setAge("fefef");
			String s="zhangsan\u001Blisiwangermazi\u001Blise";*/
			/*FileOutputStream os = new FileOutputStream(srcFullPath);
			ObjectOutputStream oos = new ObjectOutputStream(os);
			oos.writeObject(str);
			oos.flush();
			oos.close();*/
			WriteFile.fileWriter(srcFullPath, str);
			//DeleteFileUtil.delete(outPath);

			//临时文件
			String tmpFileFullPath=outPath+newFileName;

			//1对源文件进行签名
			String signValue=signFile(srcFullPath, certPath);

			//2对源文件进行加密
			String desKey = getCryKey();
			String encryptFullPath=encryptFile(desKey,srcFullPath,tmpFileFullPath);


			//3加密密串
			byte[] destByte = SM2SignUtil.encrypt(SM2SignUtil.buildPublicKey("D:\\Coding\\threadStudy\\src\\main\\webapp\\100000.puk"), desKey.getBytes());

			//4压缩
			//tmpFileFullPath=
			return zipEnpress(encryptFullPath, outPath, newFileName, signValue,BASE64Toolkit.encode(destByte));

		}catch(Exception e){
			throw new Exception("文件加密压缩失败");
		}
	}
	
	private static String encryptFile(String desKey,String enpressFullPath,String tmpFileFullPath) {
		File tmpFile=new File(tmpFileFullPath);
		if(tmpFile.exists()){
			tmpFile.delete();
		}
		SM4FileUtil.SM4EncryptFile(desKey, enpressFullPath, tmpFileFullPath);
		return tmpFileFullPath;
	}
	
	private static String  signFile(String srcFullPath,String keyName) throws Exception {

		return SM2SignUtil.sm2SignFile(srcFullPath,keyName);
	}

	private static byte[] zipEnpress(String srcFullPath,String savePathStr,String newFileName,String signValue,String destString) throws Exception {
		FileOutputStream fileOuputStream=null;
		ZipOutputStream zipOutPutStream=null;
		ByteArrayInputStream signByteStream=null;
		ByteArrayInputStream keyByteStream=null;
		FileInputStream srcFileInputStream=null;

		String zipFilePath=savePathStr+newFileName+".zip";
		File zipfile=new File(zipFilePath);
		if(zipfile.exists()){
			zipfile.delete();
		}
		byte[] bytes;
		try {
			//压缩源文�?
			fileOuputStream=new FileOutputStream(zipfile);
			zipOutPutStream = new ZipOutputStream(fileOuputStream);
			zipOutPutStream.putNextEntry(new ZipEntry(newFileName));
			srcFileInputStream=new FileInputStream(srcFullPath);
			IOUtils.copy(srcFileInputStream, zipOutPutStream);
			zipOutPutStream.closeEntry();

			//压缩签名文件
			zipOutPutStream.putNextEntry(new ZipEntry("signature.txt"));
			signByteStream=new ByteArrayInputStream(signValue.getBytes());
			IOUtils.copy(signByteStream, zipOutPutStream);

			//压缩密串
			zipOutPutStream.putNextEntry(new ZipEntry("encryptKey.txt"));
			keyByteStream=new ByteArrayInputStream(destString.getBytes());
			IOUtils.copy(keyByteStream, zipOutPutStream);
			zipOutPutStream.closeEntry();
			bytes=fileConvertToByteArray(new File(zipFilePath));

		}catch(Exception e) {
			throw e;
		}finally{
			if(keyByteStream!=null) {
				try {
					keyByteStream.close();
				} catch (IOException e) {
				}
			}
			if(signByteStream!=null) {
				try {
					signByteStream.close();
				} catch (IOException e) {
				}
			}
			if(srcFileInputStream!=null) {
				try {
					srcFileInputStream.close();
				} catch (IOException e) {
				}
			}
			if(zipOutPutStream!=null){
				try {
					zipOutPutStream.close();
				} catch (IOException e) {
				}
			}
			if(fileOuputStream!=null){
				try {
					fileOuputStream.close();
				} catch (IOException e) {
				}
			}
		}
		return bytes;
	}
	
	/**
	 * 生成随机密串
	 * @return
	 */
	public static String getCryKey() {
		RandomStringUtils rs = new RandomStringUtils();
		String verifyChars = "123457890abcdefghijklmnopqrstuvwxyz"; 
		String encryptKey = rs.random(16, verifyChars).toUpperCase();
		return encryptKey;
	}

	/**
	 * 响应数据
	 *
	 * @param response
	 * @param filename
	 * @param data
	 */
	public static void writeReturnImgData(HttpServletResponse response, String filename, byte[] data)  {

		ServletOutputStream outStream = null;
		try {
			response.setContentType("application/octet-stream");
			response.addHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(filename,"UTF-8") + ".png");
			outStream = response.getOutputStream();
			outStream.write(data);
			outStream.flush();
		} catch (Exception e) {
			//logger.error("--ResponseUtil.writeReturnImgData error--", e);
		} finally {
			if (outStream != null) {
				try {
					outStream.close();
				} catch (Exception e) {
					//logger.error("--ResponseUtil.writeReturnImgData close outStream error--", e);
				}
			}
		}
	}





	/**
	 * 下载文件
	 *
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return
	 *//*
	private ActionForward downloadZipFiles(ActionMapping mapping,
										   ActionForm form, HttpServletRequest request,
										   HttpServletResponse response) {
		ServletOutputStream out = null;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ZipOutputStream zos = new ZipOutputStream(bos);
		zos.setEncoding("GBK");//解决压缩包内文件名乱码问题
		if (caseMediationManager == null) {
			request.setAttribute("message", "系统内部错误，没有找到caseMediationManager");
			return mapping.findForward("error");
		}
		String applicationFormId = request.getParameter("applicationFormId");
		List<FileData> fileDataList = caseMediationManager.queryLicenceFiles(new BigDecimal(applicationFormId));
		try {
			response.reset();
			byte[] bs = null;
			List<byte[]> bytelist = new ArrayList<byte[]>();
			if (fileDataList.size() > 0 && fileDataList != null){
				for (int i = 0; i < fileDataList.size(); i++) {
					//压缩文件
					byte[] bytes = fileDataList.get(i).getFileStream();
					ZipEntry entry = new ZipEntry(fileDataList.get(i).getFileName());
					zos.putNextEntry(entry);
					zos.write(bytes);
				}
				zos.closeEntry();
				zos.close();
				bs = bos.toByteArray();
				bos.close();
				bytelist.add(bs);
				bs = this.bytesCombine(bytelist);
				StringBuffer sb = new StringBuffer(50);
				sb.append("attachment;filename=");
				sb.append("LICENCE.zip");
				response.setHeader("Content-Disposition", StringUtil.toUtf8String(sb.toString()));
				response.setContentType("text/html;charset=utf-8");
				out = response.getOutputStream();
				out.write(bs);
				out.flush();
			} else{
				response.setContentType("text/html");
				out = response.getOutputStream();
				OutputStreamWriter ow = new OutputStreamWriter(out,"utf-8");
				ow.write("资料下载失败！");
				ow.flush();
				ow.close();
			}
		} catch (IOException e) {
			log.error("[文件下载]：" + ExceptionDetail.getException(e));
			request.setAttribute("message", "文件下载时出错！");
			return mapping.findForward("error");
		} finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("[文件下载]：" + ExceptionDetail.getException(e));
				e.printStackTrace();
			}
		}
		return null;
	}

	*//**
	 * byte数组的合并
	 *
	 * @param srcArrays
	 * @return
	 *//*
	private byte[] bytesCombine(List<byte[]> srcArrays) {
		byte[] destArrays = null;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			for (byte[] srcArray : srcArrays) {
				bos.write(srcArray);
			}
			destArrays = bos.toByteArray();
			bos.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				bos.close();
			} catch (IOException e) {
			}
		}
		return destArrays;
	}*/


	/**
	 * 把一个文件转化为byte字节数组。
	 *
	 * @return
	 */
	private static byte[] fileConvertToByteArray(File file) {
		byte[] data = null;

		try {
			FileInputStream fis = new FileInputStream(file);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();

			int len;
			byte[] buffer = new byte[1024];
			while ((len = fis.read(buffer)) != -1) {
				baos.write(buffer, 0, len);
			}

			data = baos.toByteArray();

			fis.close();
			baos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return data;
	}
}
